#include "threadpool.h"

static
void *thread_routine(void *arg)
{
	printf("thread is starting: %d\n", GET_THREAD_ID);
	
	threadpool_t *pool = (threadpool_t *)arg;
	task_t *task = NULL;

	struct timespec abstime;
	int timeout;
	
	while(1)
	{
		timeout = 0;
		condition_lock(&pool->ready);
		pool->idle ++;

		while(pool->first == NULL && !pool->quit)
		{
			printf("thread waiting: %d\n", GET_THREAD_ID);
			
			clock_gettime(CLOCK_REALTIME, &abstime);
			
			//condition_wait(&pool->ready);	//阻塞等待
			abstime.tv_sec += 2;
			int status = condition_timewait(&pool->ready, &abstime);//超时等待
			if(status == ETIMEDOUT)
			{
				printf("thread wait time out: %d\n", GET_THREAD_ID);
				timeout = 1;
				break;
			}
		}

		pool->idle --;

		if (pool->first != NULL)
		{
			task = pool->first;
			pool->first = pool->first->next;
		}

		condition_unlock(&pool->ready);

		if (task)
		{
			task->func(task->arg);
			free(task);
			
			task = NULL;
		}

		if ((pool->quit && !pool->first) || (timeout && !pool->first))
		{	
			condition_lock(&pool->ready);
			pool->counter --;
			
			if(pool->counter == 0)
				condition_signal(&pool->ready);
			
			condition_unlock(&pool->ready);

			break;
		}

	}	

	printf("thread %d exit\n", GET_THREAD_ID);
}

threadpool_t *threadpool_create(int threads)
{
	threadpool_t *pool = calloc(1, sizeof(threadpool_t));
	if (pool == NULL)
		return NULL;

	// 初始化线程池
	condition_init(&pool->ready);

	pool->first = pool->last = NULL;
	pool->counter = pool->idle = 0;
	pool->max_threads = threads;
	pool->quit = 0;



	return pool;
}


void threadpool_destroy(threadpool_t *pool)
{
	if (pool->quit)
		return;
	
	condition_lock(&pool->ready);
	pool->quit = 1;

	if (pool->counter > 0)
	{
		if (pool->idle > 0)
			condition_broadcast(&pool->ready);

		// 处在执行任务状态的线程，不会收到广播
		// 线程池需要等待执行任务状态中的线程全部退出
		while(pool->counter > 0)
			condition_wait(&pool->ready);
	}

	condition_unlock(&pool->ready);
}

void threadpool_add_task(threadpool_t *pool, task_fuc func, void *arg)
{
	// 初始化新任务
	task_t *newtask = calloc(1, sizeof(task_t));
	newtask->func = func;
	newtask->arg = arg;
	newtask->next = NULL;

	condition_lock(&pool->ready);

	// 将任务添加到队列
	if (pool->first == NULL)
		pool->first = newtask;
	else
		pool->last->next = newtask;

	pool->last = newtask;	

	// 如果有等待线程，就唤醒其中一个去执行新任务
	if (pool->idle > 0)
	{
		condition_signal(&pool->ready);
	}
	else if (pool->counter < pool->max_threads)
	{
		pthread_t tid;
		pthread_create(&tid, NULL, thread_routine, pool);		
		pool->counter ++;
	}

	condition_unlock(&pool->ready);
}



